/* TODO
 * Check out Threadpools
 * Add Restore Functionality
 * Make sure we use bundles for JS Strings
 */

let Ci = Components.interfaces;
let Cc = Components.classes;

var gPrefs = {};

var gPrefService = null;
var gEditUIVisible = true;

const gProgressObserver = {
	observe: function(aSubject, aTopic, aData)
	{
		if(aTopic != 'progress-changed')
		{
			return;
		}

		[count, total] = eval(aData);

		if(count == 1)
		{
			/* Show Statusbar Progressmeter */
			var sbpanel = document.getElementById('statusbar-progresspanel');
			if(sbpanel)
			{
				sbpanel.collapsed = false;
			}
		}
		if(count == total)
		{
			/* Hide Statusbar Progressmeter */
			var sbpanel = document.getElementById('statusbar-progresspanel');
			if(sbpanel)
			{
				sbpanel.collapsed = true;
			}
		}

		var percentage = Math.ceil(((count / total) * 100));
		var progressMeter = document.getElementById('statusbar-icon');
		if(progressMeter)
		{
			progressMeter.value = percentage;
		}

		var sbd = document.getElementById('statusbar-display');
		if(sbd)
		{
			sbd.label = aData;
		}
	}
};

const gStatusObserver = {
	observe: function(aSubject, aTopic, aData)
	{
		if(aTopic != 'status-changed')
		{
			return;
		}

		var sbd = document.getElementById('statusbar-display');
		if(sbd)
		{
			sbd.label = aData;
		}
	}
};

const gBackupObserver = {
	observe: function(aSubject, aTopic, aData)
	{
		switch(aTopic)
		{
			case 'backup-begin':
				notifyObservers(null, 'status-changed', 'Starting backup...');	
	
				var cmdBackup = document.getElementById('cmd_backup');
				if(cmdBackup)
				{
					cmdBackup.setAttribute('disabled', true);
				}
	
				var cmdRestore = document.getElementById('cmd_restore');
				if(cmdRestore)
				{
					cmdRestore.setAttribute('disabled', true);
				}
				break;
			case 'backup-success':
				notifyObservers(null, 'status-changed', 'Backup complete.');	
	
				var cmdBackup = document.getElementById('cmd_backup');
				if(cmdBackup)
				{
					cmdBackup.removeAttribute('disabled');
				}
	
				var cmdRestore = document.getElementById('cmd_restore');
				if(cmdRestore)
				{
					cmdBackup.removeAttribute('disabled');
				}
				break;
			case 'backup-failed':
				log(aData, SD_LOG_ERROR);

				notifyObservers(null, 'status-changed', 'An error has occurred.');
				notifyObservers(null, 'progress-changed', [0, 0]);
	
				var cmdBackup = document.getElementById('cmd_backup');
				if(cmdBackup)
				{
					cmdBackup.removeAttribute('disabled');
				}
	
				var cmdRestore = document.getElementById('cmd_restore');
				if(cmdRestore)
				{
					cmdBackup.removeAttribute('disabled');
				}
				break;
		}
	}
};

const gGameObserver = {
	observe: function(aSubject, aTopic, aData)
	{
		switch(aTopic)
		{
			case 'game-on-request':
				break;
			case 'game-on-response':
				var game = eval(aData);

				/* Append Game to Game List */
				var gamelist = document.getElementById('gamelist');
				if(!gamelist)
				{
					log('Unable to find gamelist listbox.', SD_LOG_ERROR);

					notifyObservers(null, 'status-changed', 'An error has occurred.');
					return;
				}

				log('Appending Game onto Gamelist.', SD_LOG_DEBUG2);
				gamelist.appendItem(game.name, aData);

				log(game.name + ' added to the game list.', SD_LOG_INFO);

				notifyObservers(null, 'status-changed', game.name + ' added to game list.');
				break;
		}
	}
};

var gPrefObserver = {
	register: function()
	{
		var prefService = Cc["@mozilla.org/preferences-service;1"]
			.getService(Ci.nsIPrefService);
		
		this._prefBranch = prefService.getBranch('');

		this._prefBranch.QueryInterface(Ci.nsIPrefBranch2);

		this._prefBranch.addObserver('', this, false);
	},
	unregister: function()
	{
		if(!this._prefBranch)
		{
			return;
		}

		this._prefBranch.removeObserver('', this);
	},
	observe: function(aSubject, aTopic, aData)
	{
		if(aTopic != 'nsPref:changed')
		{
			return;
		}

		switch(aData)
		{
			case 'backup.destination':
				try
				{
					gPrefs[aData] = this._prefBranch.getComplexValue(aData, Ci.nsILocalFile);
				}
				catch(ex)
				{
				}
				break;
			default:
				switch(this._prefBranch.getPrefType())
				{
					case Ci.nsIPrefBranch.PREF_STRING:
						gPrefs[aData] = this._prefBranch.getCharPref(aData);
						break;
					case Ci.nsIPrefBranch.PREF_INT:
						gPrefs[aData] = this._prefBranch.getIntPref(aData);
						break;
					case Ci.nsIPrefBranch.PREF_BOOL:
						gPrefs[aData] = this._prefBranch.getBoolPref(aData);
						break;
				}
		}
	}
};
							
function Startup()
{
	gPrefService = Cc["@mozilla.org/preferences-service;1"]
		.getService(Ci.nsIPrefBranch2);

	try
	{
		gPrefs['log.level'] = gPrefService.getIntPref('log.level');
	}
	catch(ex)
	{
		gPrefs['log.level'] = SD_LOG_INFO;	
	}

	try
	{
		gPrefs['temp.remove'] = gPrefService.getBoolPref('temp.remove');
	}
	catch(ex)
	{
		gPrefs['temp.remove'] = true;
	}

	try
	{
		gPrefs['backup.destination'] = gPrefService.getComplexValue('backup.destination', Ci.nsILocalFile);
	}
	catch(ex)
	{
		gPrefs['backup.destination'] = Cc["@mozilla.org/file/directory_service;1"]
			.getService(Ci.nsIProperties)
			.get('Desk', Ci.nsIFile);
	}

	try
	{
		gPrefs['backup.archive.compression'] = gPrefService.getIntPref('backup.archive.compression');
	}
	catch(ex)
	{
		gPrefs['backup.archive.compression'] = Ci.nsIZipWriter.COMPRESSION_DEFAULT;
	}

	gPrefObserver.register();

	var os = Cc["@mozilla.org/observer-service;1"]
		.getService(Ci.nsIObserverService);
	os.addObserver(gProgressObserver, 'progress-changed', false);
	os.addObserver(gStatusObserver, 'status-changed', false);
	os.addObserver(gBackupObserver, 'backup-begin', false);
	os.addObserver(gBackupObserver, 'backup-success', false);
	os.addObserver(gBackupObserver, 'backup-failed', false);
}

function Shutdown()
{
	gPrefObserver.unregister();

	var os = Cc["@mozilla.org/observer-service;1"]
		.getService(Ci.nsIObserverService);
	os.removeObserver(gProgressObserver, 'progress-changed');
	os.removeObserver(gStatusObserver, 'status-changed');
	os.removeObserver(gBackupObserver, 'backup-begin');
	os.removeObserver(gBackupObserver, 'backup-success');
	os.removeObserver(gBackupObserver, 'backup-failed');
}

function domInspector()
{
	window.open("chrome://inspector/content/inspector.xul", "", "chrome");
}

function toJavaScriptConsole()
{
	var windowManager = Cc['@mozilla.org/appshell/window-mediator;1']
		.getService();
	var windowManagerInterface = windowManager.QueryInterface(Ci.nsIWindowMediator);
	var topWindow = windowManagerInterface.getMostRecentWindow('global:console');

	if(topWindow)
	{
		topWindow.focus();
	}
	else
	{
		window.open('chrome://global/content/console.xul', '_blank', 'chrome,extrachrome,menubar,resizable,scrollbars,status,toolbar');
	}
}

function openPreferences(paneID, extraArgs)
{
	try
	{
		var pref = Cc["@mozilla.org/preferences-service;1"]
			.getService(Ci.nsIPrefBranch);
	
		var instantApply = pref.getBoolPref("browser.preferences.instantApply");
	}
	catch(ex)
	{
		var instantApply = false;
	}

	var features = "chrome,titlebar,toolbar,centerscreen" + (instantApply ? ",dialog=no" : ",modal");

	var wm = Cc["@mozilla.org/appshell/window-mediator;1"]
		.getService(Ci.nsIWindowMediator);
	var win = wm.getMostRecentWindow("pref-window");
	if(win)
	{
		win.focus();
		if(paneID)
		{
			var pane = win.document.getElementById(paneID);
			win.document.documentElement.showPane(pane);
		}

		return win;
	}

	return openDialog("chrome://savedb/content/preferences/preferences.xul",
		"Preferences", features, paneID, extraArgs);
}

function getProxyOnUIThread(aObject, aInterface)
{
	var uiQueue = Cc["@mozilla.org/event-queue-service;1"]
		.getService(Ci.nsIEventQueueService)
		.getSpecialEventQueue(Ci.nsIEventQueueService.UI_THREAD_EVENT_QUEUE);
		
	var proxyMgr = Cc["@mozilla.org/xpcomproxy;1"]
		.getService(Ci.nsIProxyObjectManager);

	return proxyMgr.getProxyForObject(uiQueue, aInterface, aObject, NS_PROXY_SYNC | NS_PROXY_ALWAYS);
}
